/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.bytedance.scenedemo.animatiom.sipnner;

import com.bytedance.scenedemo.ResourceTable;

import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.LayoutScatter;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.utils.Rect;
import ohos.app.Context;

/**
 * PartShadowPopupView.
 *
 * @since 2021-06-17
 */
public abstract class PartShadowPopupView extends BasePopupView implements
        Component.LayoutRefreshedListener, Component.TouchEventListener {
    private static final int SECOND = 2;
    /**
     * attachPopupContainer
     */
    protected PartShadowContainer attachPopupContainer;
    /**
     * isShowUp
     */
    private boolean isShowUp;

    /**
     * PartShadowPopupView
     *
     * @param context Context
     * @param popupInfo PopupInfo
     */
    public PartShadowPopupView(Context context, PopupInfo popupInfo) {
        super(context, popupInfo);
        attachPopupContainer = (PartShadowContainer) findComponentById(ResourceTable.Id_attachPopupContainer);
        setLayoutRefreshedListener(this);
        setTouchEventListener(this);
    }

    @Override
    protected int getPopupLayoutId() {
        return ResourceTable.Layout_popup_partshadow_popup_view;
    }

    /**
     * addInnerContent
     */
    protected void addInnerContent() {
        Component contentView = LayoutScatter.getInstance(getContext()).parse(getImplLayoutId(),
                attachPopupContainer, false);
        attachPopupContainer.addComponent(contentView);
    }

    @Override
    protected void initPopupContent() {
        if (attachPopupContainer.getChildCount() == 0) {
            addInnerContent();
        }

        PopupUtils.applyPopupSize((ComponentContainer) getPopupContentView(),
                getPopupInfo(), new Runnable() {
                    @Override
                    public void run() {
                        doAttach();
                    }
                });
    }

    /**
     * initAndStartAnimation
     */
    protected void initAndStartAnimation() {
        initAnimator();
        doShowAnimation();
        doAfterShow();
    }

    @Override
    public void onRefreshed(Component component) {
        doAttach();
    }

    /**
     * doAttach
     *
     * @throws IllegalArgumentException
     */
    public void doAttach() {
        if (getPopupInfo().getAtView() == null) {
            throw new IllegalArgumentException("atView must not be null for PartShadowPopupView！");
        }

        // 1. apply width and height
        ComponentContainer.LayoutConfig params = getPopupContentView().getLayoutConfig();
        params.width = getWidth();

        // 1. 获取atView在屏幕上的位置
        int[] locations = getPopupInfo().getAtView().getLocationOnScreen();
        Rect rect = new Rect(locations[0], locations[1], locations[0] + getPopupInfo().getAtView().getWidth(),
                locations[1] + getPopupInfo().getAtView().getHeight());

        // 水平居中
        if (getPopupInfo().isCenterHorizontal() && getPopupImplView() != null) {
            // 参考目标View居中，而不是屏幕居中
            int tx = (rect.left + rect.right) / SECOND - getPopupImplView().getWidth() / SECOND;
            getPopupImplView().setTranslationX(tx);
        } else {
            int tx = rect.left + getPopupInfo().getOffsetX();
            if (tx + getPopupImplView().getWidth() > PopupUtils.getWindowWidth(getContext())) {
                // 右边超出屏幕了，往左移动
                tx -= tx + getPopupImplView().getWidth() - PopupUtils.getWindowWidth(getContext());
            }
            getPopupImplView().setTranslationX(tx);
        }

        setComponentParams(params, rect);
        getPopupContentView().setLayoutConfig(params);
        getPopupImplView().setTranslationY(getPopupInfo().getOffsetY());

        attachPopupContainer.setLongClickedListener(new LongClickedListener() {
            @Override
            public void onLongClicked(Component component) {
                if (getPopupInfo().getDismissOnTouchOutside()) {
                    dismiss();
                }
            }
        });
        initAndStartAnimation();
    }

    private void setComponentParams(ComponentContainer.LayoutConfig params, Rect rect) {
        int centerY = rect.top + rect.getHeight() / SECOND;
        if ((centerY > getHeight() / SECOND || getPopupInfo().getPopupPosition() == PopupPosition.Top)
                && getPopupInfo().getPopupPosition() != PopupPosition.Bottom) {
            params.height = rect.top; // 说明atView在Window下半部分，PartShadow应该显示在它上方，计算atView之上的高度
            isShowUp = true; // 同时自定义的impl View应该Gravity居于底部
            Component implView = ((ComponentContainer) getPopupContentView()).getComponentAt(0);
            LayoutConfig implParams = (LayoutConfig) implView.getLayoutConfig();
            implParams.setMarginBottom(getPopupInfo().getAtView().getHeight());
            implParams.alignment = LayoutAlignment.BOTTOM;
            if (getMaxHeight() != 0) {
                implParams.height = Math.min(implView.getHeight(), getMaxHeight());
            }
            implView.setLayoutConfig(implParams);
        } else {
            // atView在上半部分，PartShadow应该显示在它下方，计算atView之下的高度
            params.height = getHeight() - rect.bottom;
            isShowUp = false;
            params.setMarginTop(rect.bottom - getStatusBarHeight()); // 同时自定义的impl View应该Gravity居于顶部
            Component implView = ((ComponentContainer) getPopupContentView()).getComponentAt(0);
            LayoutConfig implParams = (LayoutConfig) implView.getLayoutConfig();
            implParams.alignment = LayoutAlignment.TOP;
            if (getMaxHeight() != 0) {
                implParams.height = Math.min(implView.getHeight(), getMaxHeight());
            }
            implView.setLayoutConfig(implParams);
        }
    }

    @Override
    protected PopupAnimator getPopupAnimator() {
        // 在下方展示
        return new ScrollScaleAnimator(getPopupContentView(), PopupAnimation.ScrollAlphaFromRightTop);
    }

    /**
     * 设置状态栏的高度，用以修正自定义位置弹窗的高度
     *
     * @return int
     */
    protected abstract int setStatusBarHeight();

    /**
     * getStatusBarHeight
     *
     * @return 状态栏高度
     */
    public int getStatusBarHeight() {
        return setStatusBarHeight();
    }

    public boolean isShowUp() {
        return isShowUp;
    }

    public void setShowUp(boolean showUp) {
        isShowUp = showUp;
    }
}
